package com.pkk.penguin.frame.know.shiro.shirodemo.util.shiro;

import com.pkk.penguin.frame.know.shiro.shirodemo.springversion.entity.TbUserEntity;
import com.pkk.penguin.frame.know.shiro.shirodemo.springversion.entity.button.Button;
import com.pkk.penguin.frame.know.shiro.shirodemo.springversion.entity.resource.ResourceRole;
import com.pkk.penguin.frame.know.shiro.shirodemo.springversion.entity.role.RoleEntity;
import com.pkk.penguin.frame.know.shiro.shirodemo.springversion.service.TbUserService;
import com.pkk.penguin.frame.know.shiro.shirodemo.util.constand.ShiroConstand;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.Sha256CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;


/**
 * @description:
 * @author: peikunkun
 * @create: 2018-08-22 15:16
 **/
@Component
public class ShiroSecurityRealm extends AuthorizingRealm {

  @Resource
  private TbUserService tbUserService;

  public ShiroSecurityRealm() {
    // This name must match the name in the SysUser class's getPrincipals() method
    setName("ShiroSecurityRealm");
    setCredentialsMatcher(new Sha256CredentialsMatcher());
  }

  /**
   * 为当前登录的用户授予角色和权限
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    Long userId = (Long) principalCollection.fromRealm(getName()).iterator().next();
    TbUserEntity user = tbUserService.selectUserInfoById(userId);
    if (user != null) {
      SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
      //查询角色
      final List<RoleEntity> roleEntities = tbUserService.selectUserRoleByUserId(userId);
      Long[] roles = new Long[roleEntities.size()];
      for (int i = 0; i < roleEntities.size(); i++) {
        RoleEntity roleEntity = roleEntities.get(i);
        info.addRole(String.valueOf(roleEntity.getId()));
        roles[i] = roleEntity.getId();
      }

      final List<ResourceRole> allResourceByRoles = tbUserService.getAllResourceByRoles(roles);
      for (int i = 0; i < allResourceByRoles.size(); i++) {
        final ResourceRole resourceRole = allResourceByRoles.get(i);
        info.addStringPermission(String.valueOf(resourceRole.getResourceId()));
        for (Button button : resourceRole.getButtonList()) {
          info.addStringPermission(String.valueOf(button.getButtonId()));
        }
      }
      return info;
    } else {
      return null;
    }
  }

  /**
   * @Description: 验证当前用户
   * @Param: [authenticationToken]
   * @return: org.apache.shiro.authc.AuthenticationInfo
   * @Author: peikunkun
   * @Date: 2018/8/23 0023 下午 12:00
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
      throws AuthenticationException {
    UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    TbUserEntity user = tbUserService.selectUserInfoByName(token.getUsername());
    if (user == null) {
      throw new AccountException("帐号或密码不正确！");
    } else if (ShiroConstand.LOCKSTAUS_TRUE.equals(user.getLockStaus())) {
      /**
       * 如果用户的status为禁用。那么就抛出<code>DisabledAccountException</code>
       */
      throw new DisabledAccountException("帐号已经禁止登录！");
    } else {
      //更新登录时间 last login time
      user.setLastLoginTime(new Date());
      tbUserService.updateUserLastLoginTimeById(user.getId());
      return new SimpleAuthenticationInfo(user.getId(), user.getPwd(), getName());
    }
  }
}
